package com.pg.auth.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pg.auth.model.dto.syslogin.LoginReq;
import com.pg.auth.model.dto.syslogin.LoginResp;
import com.pg.auth.model.entity.SysUser;
import com.pg.auth.model.mapper.SysUserMapper;
import com.pg.auth.service.SysAuthService;
import com.pg.auth.service.SysUserService;
import com.pg.base.component.PgAssert;
import com.pg.base.enums.DeleteEnum;
import com.pg.base.util.PgSecretUtil;
import com.pg.base.vo.LoginVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;


/**
 * @Description:
 * @Author: huaping.hu
 * @Date: 2022/9/7 17:53
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SysAuthServiceImpl implements SysAuthService {

    private final SysUserMapper sysUserMapper;


    @Value("${user.password.salt:'a'}")
    private String salt;

    @Value("${user.default.password:123456}")
    private String defaultPassword;


    @Override
    public LoginVO login(LoginReq req) {

        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
        LambdaQueryWrapper<SysUser> lambda = queryWrapper.lambda();

        // 兼容旧的APP版本
        if (req.getAppUser() == null) {
            //req.setAppUser(AppUserEnum.INSTITUTION.getValue());
        }

        lambda.eq(SysUser::getUserName, StringUtils.trim(req.getUsername()));
        lambda.eq(SysUser::getDeleteStatus, DeleteEnum.NORMAL.getValue());
        lambda.eq(SysUser::getPassword, PgSecretUtil.md5BySalt(req.getPassword(), salt));

        if (req.getTenantId() != null) {
            lambda.eq(SysUser::getTenantId, req.getTenantId());
        }
        lambda.orderByDesc(SysUser::getUserId);


        List<SysUser> userList = sysUserMapper.selectList(queryWrapper);


        // 账号不存在
        PgAssert.bizError(CollectionUtil.isEmpty(userList), 1,"账号不存在");

        SysUser authUser = userList.get(0);
        LoginVO loginVO = new LoginVO();
        loginVO.setUserId(authUser.getUserId());
        loginVO.setLoginName(authUser.getUserName());
        loginVO.setNickName(authUser.getNickName());
        loginVO.setTenantId(authUser.getTenantId());
        loginVO.setOrgId(authUser.getOrgId());

        //loginVO.setToken(StpUtil.getTokenValue());



        return loginVO;
    }


   /* @Override
    public LoginResp loginPhone(MiniLoginReq miniLoginReq) {
        LoginResp resp = new LoginResp();
        miniLoginReq.setNickName(miniLoginReq.getPhone());
        User authUser = getUser(miniLoginReq, 1, null);

        if (ObjectUtil.isNotEmpty(miniLoginReq.getWxCode())) {
            JSONObject jsonObject = null;
            try {
                jsonObject = getSessionKeyOrOpenId(miniLoginReq.getAppId(), miniLoginReq.getWxCode());

            } catch (IOException e) {
                throw new BizException(ResultEnum.FAIL);
            }
            if (jsonObject == null) {
                log.info("微信鉴权返回数据为null");
                throw new BizException(ResultEnum.DATA_NOT_EXIST);
            }
            log.info("微信鉴权返回数据" + jsonObject.toJSONString());
            String openid = jsonObject.getString("openid");
            log.info("openId:{}", openid);
            authUser.setRemark(openid);
        }

        setSession(authUser, Long.valueOf(miniProgramConfig.getMiniProgramAppMap().get(miniLoginReq.getAppId()).get("tenantId")), resp);

        return resp;
    }

    @Override
    public LoginResp loginWx(MiniLoginReq miniLoginReq) {
        LoginResp resp = new LoginResp();
        JSONObject jsonObject = null;
        try {
            jsonObject = getSessionKeyOrOpenId(miniLoginReq.getAppId(), miniLoginReq.getCode());

        } catch (IOException e) {
            throw new BizException(ResultEnum.FAIL);
        }
        if (jsonObject == null) {
            log.info("微信鉴权返回数据为null");
            throw new BizException(ResultEnum.DATA_NOT_EXIST);
        }
        log.info("微信鉴权返回数据" + jsonObject.toJSONString());


        String openid = jsonObject.getString("openid");
        String session_key = jsonObject.getString("session_key");
        if (openid == null || session_key == null) {
            log.info("微信鉴权错误");
            throw new BizException(ResultEnum.ERROR);
        }
        User authUser = getUser(miniLoginReq, 2, jsonObject);
        authUser.setRemark(openid);
        setSession(authUser, Long.valueOf(miniProgramConfig.getMiniProgramAppMap().get(miniLoginReq.getAppId()).get("tenantId")), resp);

        return resp;
    }


    *//**
     * 组织是否有效
     *//*
    private boolean checkOrgValid(OrgResp orgResp) {
        if (Objects.isNull(orgResp.getValidTime()) || Objects.isNull(orgResp.getLoseTime())) {
            return true;
        }
        Instant now = Instant.now();
        if (now.isBefore(orgResp.getValidTime()) || now.isAfter(orgResp.getLoseTime())) {
            return false;
        }

        return true;
    }

    private void setWorker(Long userId, LoginVO loginVO) {
        WorkerOrgResp workerOrgResp = workerOrgService.selectByUserId(userId);
        if (ObjectUtil.isNotEmpty(workerOrgResp)) {
            loginVO.setWorkerId(workerOrgResp.getWorkerId());
            loginVO.setWorkerName(workerOrgResp.getWorkerName());
        } else {
            // 如果
//            loginVO.setWorkerId(loginVO.getUserId());
//            loginVO.setWorkerName(loginVO.getNickName());
        }
    }

    private void setOrgInfo(User authUser, LoginVO loginVO) {
        OrgInfoResp orgInfoResp = orgInfoService.getByOrgId(loginVO.getOrgId());
        if (ObjectUtil.isNotEmpty(orgInfoResp)) {
            loginVO.setProvinceId(orgInfoResp.getServiceProvinceId());
            loginVO.setCityId(orgInfoResp.getServiceCityId());
            loginVO.setAreaId(orgInfoResp.getServiceAreaId());
            loginVO.setTownId(orgInfoResp.getServiceTownId());
            loginVO.setVillageId(orgInfoResp.getServiceVillageId());
            loginVO.setProvinceName(orgInfoResp.getServiceProvinceName());
            loginVO.setCityName(orgInfoResp.getServiceCityName());
            loginVO.setAreaName(orgInfoResp.getServiceAreaName());
            loginVO.setTownName(orgInfoResp.getServiceTownName());
            loginVO.setVillageName(orgInfoResp.getServiceVillageName());
        }
    }

    *//**
     * @param code
     * @return
     * @throws IOException
     *//*
    public JSONObject getSessionKeyOrOpenId(String appId, String code) throws IOException {
        //微信端登录code
        String wxCode = code;


        StringBuilder builder = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session?appid=");

        builder.append(appId);//小程序appId
        builder.append("&secret=");
        builder.append(miniProgramConfig.getMiniProgramAppMap().get(appId).get("secret"));
        builder.append("&js_code=");
        builder.append(wxCode);//小程序端返回的code
        builder.append("&grant_type=authorization_code");//默认参数

        //发送post请求读取调用微信接口获取openid用户唯一标识
        JSONObject jsonObject = HttpUtil.doGetJson(builder.toString());
        return jsonObject;
    }


    private User getUser(MiniLoginReq miniLoginReq, int type, JSONObject jsonObject) {
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(User::getMobile, miniLoginReq.getPhone()).eq(User::getUserType, UserTypeEnum.OPERATE.getValue());
        User authUser = authService.getOne(queryWrapper);
        if (authUser == null) {
            authUser = new User();
            authUser.setUserStatus(UserStatusEnum.NORMAL.getValue());
            authUser.setUserType(UserTypeEnum.OPERATE.getValue());
            authUser.setUserName(miniLoginReq.getPhone());
            authUser.setPassword(SaSecureUtil.md5BySalt(defaultPassword, salt));
            authUser.setMobile(miniLoginReq.getPhone());
            authUser.setSource(3); // 小程序来源
            authUser.setPicUrl(miniLoginReq.getPicUrl());
            authUser.setCreateUser(ClifeConstant.SYS_USER_ID);
            authUser.setCreateUserName(ClifeConstant.SYS_USER_NAME);
            authUser.setNickName(getNickName(miniLoginReq));
            authUser.setTenantId(ClifeConstant.SYS_USER_ID);
            authUser.setAppUser(AppUserEnum.BIZC.getValue());
            authUser.setOrgId(Long.valueOf(miniProgramConfig.getMiniProgramAppMap().get(miniLoginReq.getAppId()).get("tenantId")));
            authUser.setRemark("小程序注册");
            authService.save(authUser);
            if (type == 2) {
                ThirdUserAddReq thirdUser = new ThirdUserAddReq();
                thirdUser.setOpenId(jsonObject.getString("openid"));
                thirdUser.setUserId(authUser.getUserId());
                thirdUser.setUnionId(miniLoginReq.getPhone());
                thirdUser.setBindStatus(0);
                thirdUser.setThirdType(0); // 微信用
                thirdUser.setUserType(0);
                thirdUser.setTenantId(authUser.getTenantId());
                thirdUser.setOrgId(0L);
                thirdUser.setMobile(miniLoginReq.getPhone());
                thirdUserService.add(thirdUser);
            }
        }
        return authUser;
    }

    private String getNickName(MiniLoginReq miniLoginReq) {
        if (!StringUtil.isBlank(miniLoginReq.getNickName())) {
            return miniLoginReq.getNickName();
        }

        return miniLoginReq.getPhone().substring(0, 2) + "***" + miniLoginReq.getPhone().substring(9);
    }

    private void setSession(User authUser, Long tenantId, LoginResp resp) {
        Long sysId = LoginUtils.getSubSysId();

        StpUtil.login(authUser.getUserId(), "XCX" + sysId);

        LoginVO loginVO = new LoginVO();
        loginVO.setToken(StpUtil.getTokenValue());
        loginVO.setUserId(authUser.getUserId());
        loginVO.setLoginName(authUser.getUserName());
        loginVO.setNickName(authUser.getNickName());
        loginVO.setTenantId(authUser.getTenantId());
        loginVO.setOrgId(authUser.getOrgId());
        loginVO.setTenantId(authUser.getOrgId());
        loginVO.setAppUser(authUser.getAppUser());
        loginVO.setWorkerName(authUser.getRemark());
//        loginVO.setOrgTypeId(orgResp.getOrgTypeId());
//        loginVO.setOrgIdList(orgIdList);
//        loginVO.setOrgCode(orgResp.getOrgCode());
//        loginVO.setOrgLevel(orgResp.getOrgLevel());
//        loginVO.setOrgName(orgResp.getOrgName());
//        loginVO.setParentOrgId(orgResp.getParentId());
//        loginVO.setOrgLevelTree(orgResp.getOrgTree());
//        loginVO.setRoleIds(Arrays.asList(ObjectUtil.isNotEmpty(roleUser)? roleUser.getRoleId() : 0));

//        //设置登录用户服务五级地址
//        setOrgInfo(authUser, loginVO);
//        // 设置登录用户关联员工
//        setWorker(userId, loginVO);

        log.info("login user[{}]", JSON.toJSONString(loginVO));

        StpUtil.getSession().set("loginUser", loginVO);
        final UserExtResp userExtResp = userExtService.getByUserId(authUser.getUserId());

        if (userExtResp == null || userExtResp.getIdCardNo() == null || userExtResp.getRealName() == null) {
            resp.setIsRealNameAuth(0); // 默认 未认证
        } else {
            resp.setIsRealNameAuth(1); // 已实名认证
        }
        resp.setNickName(loginVO.getNickName());
        resp.setToken(StpUtil.getTokenValue());

        authService.updateOnlineStatus(authUser.getUserId(), OnlineStatusEnum.ONLINE);
    }

    @Override
    public LoginResp userLogin(String token, Integer type) {
        LoginResp resp = new LoginResp();
        if (type == null) {
            type = 1;
        }
        String linkUrl;
        switch (type) {
            case 0:
                linkUrl = DigitalCountrysideUtil.LINK_ITEST_DIGITAL_COUNTRYSIDE_DOMAIN;
                break; //可选
            case 1:
                linkUrl = DigitalCountrysideUtil.LINK_CMS_DIGITAL_COUNTRYSIDE_DOMAIN;
                break; //可选
            case 2:
                linkUrl = DigitalCountrysideUtil.LINK_FORMAL_DIGITAL_COUNTRYSIDE_DOMAIN;
                break; //可选
            default:
                linkUrl = DigitalCountrysideUtil.LINK_ITEST_DIGITAL_COUNTRYSIDE_DOMAIN;
                break; //可选
        }

        //获取accessToken开始
        Map<String, String> accessTokenParamMap = new HashMap<>();
        Map<String, String> accessTokenHeadersMap = new HashMap<>();
        accessTokenParamMap.put("appId", DigitalCountrysideUtil.getCountrySideAppId());
        accessTokenParamMap.put("appSecret", DigitalCountrysideUtil.getCountrySideAppSecret());
        accessTokenParamMap.put("timestamp", DigitalCountrysideUtil.getTimeStamp());

        String accessTokenInfoJsonString = null;
        try {
            accessTokenInfoJsonString = HttpClientUtils.
                    getRequest(DigitalCountrysideUtil.getAccessTokenUrl(), accessTokenParamMap, accessTokenHeadersMap);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        log.info("accessTokenInfoJsonString:{}", JSON.toJSONString(accessTokenInfoJsonString));
        JSONObject accessTokenJsonObject = JSON.parseObject(accessTokenInfoJsonString);
        log.info("accessTokenJsonObject:{}", JSON.toJSONString(accessTokenJsonObject));
        log.info("accessTokenJsonObject.data:{}", JSON.toJSONString(accessTokenJsonObject.getJSONObject("data")));
        JSONObject accessTokenDataJson = accessTokenJsonObject.getJSONObject("data");
        log.info("accessTokenDataJson:{}", JSON.toJSONString(accessTokenDataJson));

        //获取到accessToken结束
        String accessTokenFromCertificationCenter = accessTokenDataJson.getString("accessToken");
        log.info("accessTokenFromCertificationCenter:{}", JSON.toJSONString(accessTokenFromCertificationCenter));

        //----------------------------------------------------

        //获取认证中心认证信息开始
        Map<String, String> headersMap = new HashMap<>();
        Map<String, String> paramMap = new HashMap<>();

        paramMap.put("accessToken", accessTokenFromCertificationCenter);
        paramMap.put("appId", DigitalCountrysideUtil.getCountrySideAppId());
        paramMap.put("timestamp", DigitalCountrysideUtil.getTimeStamp());
        log.info("token:{}", JSON.toJSONString(token));
        paramMap.put("token", token);
        paramMap.put("sign", DigitalCountrysideUtil.getSign(DigitalCountrysideUtil.getReuquestUrl(DigitalCountrysideUtil.getCheckAuthUrl(linkUrl), paramMap), "POST", DigitalCountrysideUtil.getCountrySideAppSecret()));

        log.info("loginparamMap{}", paramMap.toString());

        String checkAuthInfoJsonString = null;
        log.info("linkUrl:{}", JSON.toJSONString(linkUrl));
        log.info("paramMap:{}", JSON.toJSONString(paramMap));
        log.info("headersMap:{}", JSON.toJSONString(headersMap));
        try {
            checkAuthInfoJsonString = HttpClientUtils.postRequest(DigitalCountrysideUtil.getCheckAuthUrl(linkUrl), paramMap, headersMap, null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("checkAuthInfoJsonString:{}", JSON.toJSONString(checkAuthInfoJsonString));
        JSONObject checkAuthDataJson = JSON.parseObject(checkAuthInfoJsonString);

        log.info("checkAuthDataJson:{}" + checkAuthDataJson.toJSONString());

        JSONObject phoneData = checkAuthDataJson.getJSONObject("data");
        if (phoneData == null) {
            if (!"0".equals(checkAuthDataJson.get("code"))) {
                throw new BizException(999998, checkAuthDataJson.get("msg").toString());
            }
            throw new BizException(999999, "token无效");
        }
        log.info("phoneData:{}" + phoneData.toJSONString());


        //获取到认证中心认证信息结束
        String userName = phoneData.getString("userName");
        String tenantId = phoneData.getString("tenantId");
        Long sysId = phoneData.getLong("sysId");

        //查询用户信息
        LoginReq req = new LoginReq();
        req.setUsername(userName);
        req.setTenantId(Long.getLong(tenantId));
        req.setMark("0");
        List<User> authUserList = authService.login(req);
        log.info("authUserList用户信息::" + JSON.toJSONString(authUserList));
        // 账号不存在
        ClifeAssert.bizError(CollectionUtil.isEmpty(authUserList), ErrorCodeEnum.LOGIN_ERROR);
        // 同账号在不同租户，需要选择组织
        ClifeAssert.bizError(authUserList.size() > 1, ErrorCodeEnum.LOGIN_USER_MORE);
        User authUser = authUserList.get(0);
        log.info("authUser::" + JSON.toJSONString(authUser));

        // 账号禁止登录
        ClifeAssert.bizError(UserStatusEnum.DISABLED.getValue().equals(authUser.getUserStatus()), ErrorCodeEnum.LOGIN_DISABLE);

        OrgResp orgResp = orgService.getById(authUser.getOrgId());
        log.info("orgResp组织信息::" + JSON.toJSONString(orgResp));

        // 组织禁止登录
        ClifeAssert.bizError((orgResp == null ? true : OrgStatusEnum.FREEZE.getValue().equals(orgResp.getOrgStatus())), ErrorCodeEnum.ORG_FREEZE);

        Long userId = authUser.getUserId();

        RoleUser roleUser = roleUserService.getByUserId(userId);
        log.info("roleUser角色信息::" + JSON.toJSONString(roleUser));
        //        Long sysId = LoginUtils.getSubSysId();
        //Long sysId = 3L;

        // 验证账号是否有权登录系统
        ClifeAssert.bizError(!subSysService.validLoginSys(sysId, roleUser), ErrorCodeEnum.NO_ACCESS_SYS);

        List<Long> orgIdList = orgService.listOrgIdAndChild(orgResp.getOrgTree());

        StpUtil.login(userId, req.getDevice() + sysId);

        LoginVO loginVO = new LoginVO();
        loginVO.setToken(StpUtil.getTokenValue());
        loginVO.setUserId(userId);
        loginVO.setLoginName(authUser.getUserName());
        loginVO.setNickName(authUser.getNickName());
        loginVO.setTenantId(authUser.getTenantId());
        loginVO.setOrgId(authUser.getOrgId());
        loginVO.setOrgIdList(orgIdList);
        loginVO.setOrgCode(orgResp.getOrgCode());
        loginVO.setOrgLevel(orgResp.getOrgLevel());
        loginVO.setOrgName(orgResp.getOrgName());
        loginVO.setParentOrgId(orgResp.getParentId());
        loginVO.setOrgLevelTree(orgResp.getOrgTree());
        loginVO.setRoleIds(Arrays.asList(ObjectUtil.isNotEmpty(roleUser) ? roleUser.getRoleId() : 0));

        //设置登录用户服务五级地址
        setOrgInfo(authUser, loginVO);
        // 设置登录用户关联员工
        setWorker(userId, loginVO);

        log.info("login user[{}]", JSON.toJSONString(loginVO));

        StpUtil.getSession().set("loginUser", loginVO);
        resp.setNickName(loginVO.getNickName());
        resp.setToken(StpUtil.getTokenValue());

        authService.updateOnlineStatus(userId, OnlineStatusEnum.ONLINE);

        return resp;
    }

    @Override
    public int switchTenant(Long tenantId) {

        LoginVO loginUser = LoginUtils.getLoginUser();

        log.info("----------> switch tenant [{}],[{}]", tenantId, JSON.toJSONString(loginUser));

        loginUser.setTenantId(tenantId);

        StpUtil.getSession().set("loginUser", loginUser);

        // 将租户ID更新到数据库中
        UserUpdateReq user = new UserUpdateReq();
        user.setOrgId(tenantId);
        user.setUserId(loginUser.getUserId());
        userService.updateInfo(user);

        // 将C端账号关系同步到用户租户表中
        UserOrgUpdateReq userOrgUpdateReq = new UserOrgUpdateReq();
        userOrgUpdateReq.setUserId(loginUser.getUserId());
        userOrgUpdateReq.setUserType(UserTypeEnum.OPERATE.getValue());
        userOrgUpdateReq.setUserStatus(1);
        userOrgUpdateReq.setTenantId(loginUser.getTenantId());
        userOrgUpdateReq.setOrgId(0L);

        userOrgService.save(userOrgUpdateReq);

        return 1;
    }
*/






}